package com.shinbada.modules.competitor.service;

import com.google.common.collect.Maps;
import com.shinbada.core.persistence.Page;
import com.shinbada.core.service.CrudService;
import com.shinbada.excel.ExcelKit;
import com.shinbada.excel.handler.DefaultExcelReadStrategyHandlerV3;
import com.shinbada.excel.modle.CheckResult;
import com.shinbada.excel.modle.ImportExcelResult;
import com.shinbada.excel.modle.StrategyCheckService;
import com.shinbada.excel.modle.UploadModle;
import com.shinbada.modules.competitor.entity.CompetitorProduct;
import com.shinbada.modules.competitor.entity.CompetitorProductDataItem;
import com.shinbada.modules.competitor.entity.DTO.CompetitorProductDTO;
import com.shinbada.modules.competitor.entity.DTO.ParamModelSelectionDTO;
import com.shinbada.modules.competitor.entity.VO.CompetitorDataItemVO;
import com.shinbada.modules.competitor.entity.VO.CompetitorResultVO;
import com.shinbada.modules.competitor.mapper.CompetitorProductMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 产品基础表Service
 *
 * @author initcap
 * @version 2021-08-04
 */
@Service
@Transactional(readOnly = true)
public class CompetitorProductService extends CrudService<CompetitorProductMapper, CompetitorProduct> implements StrategyCheckService<CompetitorProduct> {

    @Autowired
    private CompetitorProductDataItemService competitorProductDataItemService;

	@Autowired
	private CompetitorProductDataItemValueService competitorProductDataItemValueService;

    private Map<String, String> dataItemMap;

    private Map<String, String> keys;

    @Override
    public CompetitorProduct get(String id) {
        return super.get(id);
    }

    @Override
    public List<CompetitorProduct> findList(CompetitorProduct competitorProduct) {
        return super.findList(competitorProduct);
    }

    @Override
    public Page<CompetitorProduct> findPage(Page<CompetitorProduct> page, CompetitorProduct competitorProduct) {
        return super.findPage(page, competitorProduct);
    }

    @Transactional(readOnly = false)
    @Override
    public void save(CompetitorProduct competitorProduct) {
        super.save(competitorProduct);
    }

    @Transactional(readOnly = false)
    @Override
    public void delete(CompetitorProduct competitorProduct) {
        super.delete(competitorProduct);
    }

    @Transactional(readOnly = false)
    @SneakyThrows
    public ImportExcelResult<CompetitorProduct> uploadExcel(MultipartFile file, UploadModle modle) {
        // 1. 准备提前数据
        readExcelInit();
        // 2. 添加数据处理器
        DefaultExcelReadStrategyHandlerV3<CompetitorProduct> excelReadHandler = new DefaultExcelReadStrategyHandlerV3<>(modle, this);
        // 3. 执行导入
        ExcelKit.$Import(CompetitorProduct.class).readXlsx(file.getInputStream(), excelReadHandler);
        // 4. 获得导入结果集
        ImportExcelResult<CompetitorProduct> importExcelResult = excelReadHandler.results();
        // 5. 批量添加成功数据
        importExcelResult.getSuccessList().forEach(this::save);
        // 返回结果,成功的数据不返回了，影响响应速度
        importExcelResult.setSuccessList(null);
        return importExcelResult;

    }

    /**
     * @param entity 实体类
     * @return 这个key的获取决定了，在Excel导入的时候需要校验的唯一标准
     */
    private String getReadExcelKey(CompetitorProduct entity) {
        return entity.getId() + entity.getRemarks();
    }

    private void readExcelInit() {
        // 获取到现在数据库中的所有数据
        List<CompetitorProduct> db = mapper.findAllList(new CompetitorProduct());
        this.keys = Maps.newHashMapWithExpectedSize(db.size());
        // 转换键配置,请根据必要条件实现，直接使用会有问题
        db.forEach(entity -> this.keys.put(getReadExcelKey(entity), entity.getId()));
    }

    @Override
    public CheckResult readAndCheck(CompetitorProduct entity) {
        // 验证重复数据,请根据必要条件实现，直接使用会有问题
        String key = getReadExcelKey(entity);
        if (this.keys.containsKey(key)) {
            entity.setId(this.keys.get(key));
            return CheckResult.cover(key);
        }
        // 添加数据
        this.keys.put(key, "");
        return CheckResult.pass(key);
    }

    public List<CompetitorResultVO> productList(CompetitorProductDTO competitorProductDTO) {
        List<CompetitorResultVO> competitorResultVOS = mapper.productList(competitorProductDTO);
        return competitorResultVOS;
    }

    public List<CompetitorResultVO> modelSelection(String type, List<ParamModelSelectionDTO> paramModelSelectionDTOList) {
        // 根据类型获取数据项
        List<CompetitorProductDataItem> competitorProductDataItemList = competitorProductDataItemService.selectDataItemByType(type);
        this.dataItemMap = competitorProductDataItemList.stream().collect(Collectors.toMap(CompetitorProductDataItem::getName, CompetitorProductDataItem::getId));
        // 获取数据项id 追加到集合中
        paramModelSelectionDTOList.stream().forEach(paramModelSelectionDTO -> paramModelSelectionDTO.setId(this.dataItemMap.get(paramModelSelectionDTO.getName())));
		// 根据集合获取 数据项ids
		String[] productIds = competitorProductDataItemValueService.selectProductIdsByItemIdAndValue(paramModelSelectionDTOList);
		// 根据产品ids 获取指定产品数据结构
        List<CompetitorResultVO> list = mapper.productListByIds(productIds);
        // 集合转map
        listToMap(list);
        return list;
    }

    /**
     * 竞品推荐
     * @param
     * @param competitorProductDTO
     * @return
     */
    public List<CompetitorResultVO> competitorRecommend( CompetitorProductDTO competitorProductDTO) {
        // 获取常用数据项以及数据项数值
        List<CompetitorResultVO> competitorResultVOS = mapper.productList(competitorProductDTO);
        //初始化 竞品推荐常用参数
        List<ParamModelSelectionDTO> paramModelSelectionDTOList = new ArrayList<>();
        for (CompetitorResultVO competitorResultVO : competitorResultVOS) {
            for (CompetitorDataItemVO competitorDataItemVO : competitorResultVO.getCompetitorDataItemVOS()) {
                ParamModelSelectionDTO paramModelSelectionDTO = new ParamModelSelectionDTO();
                paramModelSelectionDTO.setId(competitorDataItemVO.getDataItemId());
                paramModelSelectionDTO.setName(competitorDataItemVO.getDataItemName());
                paramModelSelectionDTO.setValue(competitorDataItemVO.getValue());
                paramModelSelectionDTOList.add(paramModelSelectionDTO);
            }
        }
        // 根据数据项和数据项数值获取 产品ids
        String[] productIds = competitorProductDataItemValueService.selectProductIdsByItemIdAndValue(paramModelSelectionDTOList);
        // 根据产品ids 获取指定产品数据结构
        List<CompetitorResultVO> list = mapper.productListByIds(productIds);
        // 集合转map
        listToMap(list);
        return list;
    }

    /**
     * 集合数据转成map数据
     * @param list
     */
    private void listToMap(List<CompetitorResultVO> list) {
        for (CompetitorResultVO competitorResultVO : list) {
            Map<String, CompetitorDataItemVO> map = competitorResultVO.getCompetitorDataItemVOS().stream()
                    .collect(Collectors.toMap(CompetitorDataItemVO::getDataItemId, o -> o, (o, o1) -> o));
            competitorResultVO.setCompetitorDataItemVOMap(map);
            competitorResultVO.setCompetitorDataItemVOS(null);
        }
    }
}
